Imports System.Net.Mail
Namespace Net
  ''' <summary>
  ''' Mail helper class.
  ''' </summary>
  ''' <remarks></remarks>
  Public NotInheritable Class Mailer

    ''' <summary>
    ''' Event fired when Async mail send completed.
    ''' </summary>
    ''' <remarks></remarks>
    Public Event SendMailAsyncCompleted As EventHandler(Of System.ComponentModel.AsyncCompletedEventArgs)

    Private _mailServer As System.Net.Mail.SmtpClient

    ''' <summary>
    ''' Sends mail.
    ''' </summary>
    ''' <param name="sendFrom">From email address.</param>
    ''' <param name="subject">Subject.</param>
    ''' <param name="message">Message.</param>
    ''' <param name="bodyHtml">Sets message is HTML.</param>
    ''' <param name="sendToAddresses">Send to email addresses.</param>
    ''' <remarks></remarks>
    Public Sub SendMail(ByVal sendFrom As EmailAddress, ByVal subject As String, ByVal message As String, ByVal bodyHtml As Boolean, ByVal sendToAddresses As System.Collections.ObjectModel.ReadOnlyCollection(Of EmailAddress))
      Dim tempMessage As New MailMessage()

      Me.CreateMailMessage(sendFrom, subject, message, bodyHtml, sendToAddresses, tempMessage)

      Me.SendMailMessage(tempMessage, Nothing)

    End Sub

    ''' <summary>
    ''' Sends mail.
    ''' </summary>
    ''' <param name="sendFrom">From email address.</param>
    ''' <param name="subject">Subject.</param>
    ''' <param name="message">Message.</param>
    ''' <param name="bodyHtml">Sets message is HTML.</param>
    ''' <param name="sendToAddress">Send to email address.</param>
    ''' <remarks></remarks>
    Public Sub SendMail(ByVal sendFrom As EmailAddress, ByVal subject As String, ByVal message As String, ByVal bodyHtml As Boolean, ByVal sendToAddress As EmailAddress)

      Me.SendMail(sendFrom, subject, message, bodyHtml, sendToAddress)

    End Sub

    ''' <summary>
    ''' Sends mail.
    ''' </summary>
    ''' <param name="message">Message object.</param>
    ''' <remarks></remarks>
    Public Sub SendMail(ByVal message As MailMessage)

      Me.SendMailMessage(message, Nothing)

    End Sub

    ''' <summary>
    ''' Sends mail async.
    ''' </summary>
    ''' <param name="sendFrom">From email address.</param>
    ''' <param name="subject">Subject.</param>
    ''' <param name="message">Message.</param>
    ''' <param name="bodyHtml">Sets message is HTML.</param>
    ''' <param name="userToken">User token for async.</param>
    ''' <param name="sendToAddresses">Send to email addresses.</param>
    ''' <remarks></remarks>
    Public Sub SendMailAsync(ByVal sendFrom As EmailAddress, ByVal subject As String, ByVal message As String, ByVal bodyHtml As Boolean, ByVal userToken As Object, ByVal sendToAddresses As System.Collections.ObjectModel.ReadOnlyCollection(Of EmailAddress))
      Dim tempMessage As New MailMessage()

      Me.CreateMailMessage(sendFrom, subject, message, bodyHtml, sendToAddresses, tempMessage)

      Me.SendMailMessage(tempMessage, userToken)

    End Sub

    ''' <summary>
    ''' Sends mail async.
    ''' </summary>
    ''' <param name="sendFrom">From email address.</param>
    ''' <param name="subject">Subject.</param>
    ''' <param name="message">Message.</param>
    ''' <param name="bodyHtml">Sets message is HTML.</param>
    ''' <param name="userToken">User token for async.</param>
    ''' <param name="sendToAddress">Send to email address.</param>
    ''' <remarks></remarks>
    Public Sub SendMailAsync(ByVal sendFrom As EmailAddress, ByVal subject As String, ByVal message As String, ByVal bodyHtml As Boolean, ByVal userToken As Object, ByVal sendToAddress As EmailAddress)

      Dim address As New System.Collections.Generic.List(Of EmailAddress)

      address.Add(sendToAddress)

      Me.SendMailAsync(sendFrom, subject, message, bodyHtml, userToken, New System.Collections.ObjectModel.ReadOnlyCollection(Of EmailAddress)(address))

    End Sub

    ''' <summary>
    ''' Sends mail async.
    ''' </summary>
    ''' <param name="message">Message object.</param>
    ''' <param name="userToken">User token for async.</param>
    ''' <remarks></remarks>
    Public Sub SendMailAsync(ByVal message As MailMessage, ByVal userToken As Object)

      Me.SendMailMessage(message, userToken)

    End Sub

    Private Sub CreateMailMessage(ByVal sendFrom As EmailAddress, ByVal subject As String, ByVal message As String, ByVal bodyHtml As Boolean, ByVal sendToAddresses As System.Collections.ObjectModel.ReadOnlyCollection(Of EmailAddress), ByVal tempMessage As MailMessage)

      For Each tempSendTo As EmailAddress In sendToAddresses
        If tempSendTo.IsAddressValid Then
          tempMessage.To.Add(New MailAddress(tempSendTo.Address, tempSendTo.Name))
        End If
      Next

      tempMessage.From = New MailAddress(sendFrom.Address, sendFrom.Name)
      tempMessage.Subject = subject
      tempMessage.Body = message
      tempMessage.IsBodyHtml = bodyHtml

    End Sub

    ''' <summary>
    ''' Sends email with the users default email applicaitons.
    ''' </summary>
    ''' <param name="subject">Subject of the email.</param>
    ''' <param name="message">Email message</param>
    ''' <param name="sendToAddress">Email address to send to.</param>
    ''' <remarks></remarks>
    Public Shared Sub SendMailWithDefaultProgram(ByVal subject As String, ByVal message As String, ByVal sendToAddress As EmailAddress)

      If sendToAddress.IsAddressValid Then

        Dim mailProcess As New Process()
        Dim processInfo As New System.Diagnostics.ProcessStartInfo()

        processInfo.FileName = String.Format(CultureInfo.InvariantCulture, "mailto:{0}?subject={1}&body={2}", sendToAddress.Address, subject, message)
        processInfo.UseShellExecute = True
        processInfo.WindowStyle = ProcessWindowStyle.Normal
        mailProcess.StartInfo = processInfo
        Process.Start(processInfo)

      Else
        Throw New ArgumentException("sendTo")
      End If

    End Sub

    ''' <summary>
    ''' Creates read-only list of email addresses.
    ''' </summary>
    ''' <param name="emailAddresses">Array of email addresses.</param>
    ''' <returns>Collection of <see cref="System.Collections.ObjectModel.ReadOnlyCollection(Of EmailAddress)"></see></returns>
    ''' <remarks></remarks>
    Public Shared Function CreateEmailAddressList(ByVal ParamArray emailAddresses() As String) As System.Collections.ObjectModel.ReadOnlyCollection(Of EmailAddress)
      Dim addresses As New System.Collections.Generic.List(Of EmailAddress)

      For Each address As String In emailAddresses
        addresses.Add(New EmailAddress(address))
      Next

      Return New System.Collections.ObjectModel.ReadOnlyCollection(Of EmailAddress)(addresses)

    End Function

    Private Sub SendMailMessage(ByVal tempMessage As MailMessage, ByVal userToken As Object)

      If Not IsNothing(userToken) Then
        AddHandler _mailServer.SendCompleted, AddressOf SendAsyncCompleted
        Me._mailServer.SendAsync(tempMessage, userToken)
      Else
        Me._mailServer.Send(tempMessage)
      End If

    End Sub

    Private Sub SendAsyncCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)

      RaiseEvent SendMailAsyncCompleted(Me, e)

      RemoveHandler _mailServer.SendCompleted, AddressOf SendAsyncCompleted

    End Sub

    ''' <summary>
    ''' Timeout for the SMTP server.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Timeout() As Int32
      Get
        Return Me._mailServer.Timeout
      End Get
      Set(ByVal value As Int32)
        Me._mailServer.Timeout = value
      End Set
    End Property

    ''' <summary>
    ''' Constructor
    ''' </summary>
    ''' <param name="host">SMTP host address (required).</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal host As String)
      Me._mailServer = New System.Net.Mail.SmtpClient(host)
    End Sub

    ''' <summary>
    ''' Constructor
    ''' </summary>
    ''' <param name="host">SMTP host address (required)</param>
    ''' <param name="port">SMTP host port (required)</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal host As String, ByVal port As Int32)
      Me._mailServer = New System.Net.Mail.SmtpClient(host, port)
    End Sub

  End Class
End Namespace